import React, { Component } from 'react'

import {
  ArrowRightOutlined,
  AudioOutlined,
  CheckOutlined,
  CloseOutlined,
  createFromIconfontCN,
  DeleteOutlined,
  EditOutlined,
  QuestionCircleOutlined,
  SearchOutlined,
  SwapRightOutlined,
  TagsOutlined,
} from '@ant-design/icons';

import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';

import {
  Badge,
  Button,
  Col,
  Drawer,
  Empty,
  Input,
  message,
  Modal,
  notification,
  Popconfirm,
  Popover,
  Progress,
  Row,
  Tabs,
  Tooltip,
} from 'antd';
import {getMark, labelPre, modifyMarkContent, resetMark, submitMark} from '@/services/mark';
import labelPng from '@/assets/label.png'
import singleEntity1 from '@/assets/singleEntity1.png'
import singleEntity2 from '@/assets/singleEntity2.png'
import singleRelation1 from '@/assets/singleRelation1.png'
import singleRelation2 from '@/assets/singleRelation2.png'
import multipleEntity1 from '@/assets/multipleEntity1.png'
import multipleEntity2 from '@/assets/multipleEntity2.png'
import multipleRelation1 from '@/assets/multipleRelation1.png'
import multipleRelation2 from '@/assets/multipleRelation2.png'
import { createUUID } from '@/utils/utils';
import styles from '../style.less';
import {
  clearSelect,
  getContent,
  getDeleteContent,
  getIndexByContent,
  getMarkContent,
  getNum,
  getTypeById,
  initTitle,
  queryIndex, queryLabelContent, computeInitTxtArr
} from './config'
import { wrap } from 'lodash';
import WebSocket from "@/utils/webSocket";
import FloatWindow from "@/pages/algorithmModel/mark/components/audioMarkFloatWindow";
import {getAudioMarkContent, questionLabelGetIndexByContent} from "@/pages/algorithmModel/mark/components/config";
import AudioMultipleRelationModal from "@/pages/algorithmModel/mark/components/audioMultipleRelationModal";
import unAudio from "@/assets/unAudio.png";
import {number} from "prop-types";
const IconFont = createFromIconfontCN({
  scriptUrl: '//at.alicdn.com/t/font_3273667_1ie7zknzte6.js',
});
const { TextArea } = Input;
const { confirm } = Modal;
const { TabPane } = Tabs;
const { Search } = Input;
const colors = ['#ff7100', '#ff9800', '#3bbf45', '#37bc9b', '#1890ff', '#314ed2', '#664be8', '#a94be8',
  '#e84b9c', '#ee4e53', '#b0a4e3', '#ffb61e', '#ffa400', '#fa8c35', '#afdd22', '#e9bb1d', '#e29c45',
  '#ca6924', '#96ce54', '#16a951', '#21a675', '#48c0a3', '#dc3023', '#f36838', '#f9906f', '#1685a9', '#4b5cc4', '#4c8dae'];
let timer = null;

class Mark extends Component {
  constructor(props) {
    super(props);
    this.state = {
      entityMap: {},
      initTxt: '',
      objectLabels: [], // 实体
      propLabels: [], // 实体属性
      propertyIdArr: [], // 标注文档中的属性UUID
      initTxtArr: [], // 标注后的文档
      relationArr: [], // 已添加的关系
      relations: [], // 关系
      editEntity: {}, // 正在编辑的实体
      dataSetId: '', // 数据集id
      markId: '', // 当前标注任务的id
      id: '', // 判定关系标识符
      Heights: '', // 列表高度-标签占的高度
      labelId: '', // 模式0 下 选中的标签 id
      labelText: '', // 模式0 下 选中的标签 text
      labelType: '', // 模式0下 选中标签的类型 如有属性抽取时为property
      markModel: 1, // 标注模式 1：先划词 后标注（单个标注） 0：先选标签 后划词（批量标注）
      markType: 0, // 标注类型  0：实体 3关键词 1：关系 4:属性  5：事件
      searchValue: '', // 实体搜索关键字
      searchValue2: '', // 实体属性搜索关键字
      searchTopValue: '', // 头部搜索 关键字
      searchVisible: false, // 是否显示搜索框
      isDelete: false, // 是否打开删除实体询问层
      delIndex: '', // 删除实体索引  用于判断是否打开删除实体询问层
      isOpenDrawer: false, // 是否开启抽屉
      isMarked: false, // 是否已提交
      relationKeyword: '',
      tempRelationKeyword: '',
      process: {}, // 进度
      drawerSearch: '', // 抽屉搜索内容
      drawerSearchProp: '',
      drawerSearchPropRe: '',
      drawerSearchRe: '',
      needSave: false, // 用以记录是否有变更 如果有 则触发提交
      isModify: false, // 修改框的显示
      objects: [], // 触发词列表 初始化中在objectLabelList中读取并存到此处
      preLabelStatus: 0, // 预标注状态 0 未发起预标注 1 预标注中 2 完成预标注
      usedLabel: false, // 使用了标签的标识 true 使用了标签信息 false 未使用标签信息
      labelTextId: 0, // 预标注文本id
      entityObj: {},
      unRepeatedLabelRelationArr: [], //标签与标签如果有多个角色、多个关系取，去重
      unRepeatedLabelRelationObj: [], //标签与标签如果有多个角色、多个关系取，去重
      relationFromToName: '', //当前标签标签
      chooseMultiVisible: {}, // 多角色选择弹框展示
      audioModalVisible:false, // 语音标注浮窗
      audioMultipleRelationModalVisible:false, // 语音标注起始标签和目标标签之间有多个关系时
      multipleRelationObj:{},// 语音标注起始标签和目标标签之间有多个关系时,存储多个关系
      multipleRelationStartLabel:"" ,// 语音标注起始标签和目标标签之间有多个关系时,起始标签
      multipleRelationTargetLabel:[] ,// 语音标注起始标签和目标标签之间有多个关系时,目标标签，为array，目标标签可能有多个
      targetLabelIsNotExistNum: 0, //目标实体不存在个数
      relationLabelIsNotExistNum: 0, // 两个实体之间没有关系的个数
      effectAudio: true, // 没有检测到有效声音，请再试一次，为true时是有效声音
      addQuestionLabelVisible:false,
      labelList:[], //阅读理解问题标签
      questionLabelOnMouseEnterId:'', // 鼠标覆盖的当前目标标签
      questionLabelOnMouseEnterIdDrawer:'', // 抽屉鼠标覆盖的当前目标标签
      isDeleteLabel:false,//点击删除标签
      questionLabelModifyId:0,// 编辑的标签id
      questionLabelName: '',// 当前新增、编辑的问题标签内容
    };
  }

  componentDidMount() {
    this.props.onRef(this)
    const Heights = document.getElementById('contentBox').offsetHeight - document.getElementById(
      'lableBoxs').offsetHeight;
    // 清除定时提交
    clearInterval(timer);
    // eslint-disable-next-line max-len
    this.setState({
      Heights,
      needSave: false,
      markId: this.props.id,
      markType: this.props.markType,
      firstSave: true,
    }, () => {
      this.queryTaskInfo()
    });
  }

  componentWillReceiveProps(nextProps) {
    const { markType, id } = nextProps;
    this.setState({
      markType,
      needSave: false,
      markId: id,
    }, () => {
      // this.queryTaskInfo()
    })
  }

  componentWillUnmount() {
    // 清除定时提交
    clearInterval(timer);
  }

  thisIsFunc(initTxtArr, propertyIdArr, objectLabelList, propLabels) {
    // 标注的实体index
    const { entityObj, markType } = this.state
    initTxtArr && initTxtArr.map(item => {
      const arr = item.split('$_#_$')
      const isProp = propertyIdArr && propertyIdArr.length > 0 &&
        propertyIdArr.indexOf(arr[3]) > -1;
      if (isProp) {
        entityObj[arr[3]] = objectLabelList.length + propLabels.findIndex(label => label.labelName === arr[1]);
      } else {
        entityObj[arr[3]] = objectLabelList.findIndex(label => label === arr[1]);
      }
    })
    this.setState({ entityObj })
  }

  // 获取任务详情
  queryTaskInfo() {
    const { markId } = this.state;
    const that = this;
    markId && getMark(markId)
      .then(res => {
        if (res.retCode === '0') {
          // eslint-disable-next-line max-len
          const { initTxt, initTxtArr, relationLabelList, propertyIdArr, relationArr, objectLabelList, dataSetId, labelProcess, segmentNum, isMarked, preLabelStatus, usedLabel, id,labelList } = res.data;
          // eslint-disable-next-line max-len
          // 获取触发词列表
          let objects = []
          objectLabelList.forEach(object => {
            if (object.labelType === 0) {
              objects.push(object.labelName)
            }
          })
          const entityNum = {}
          initTxtArr && initTxtArr.map(item=>{
            if (item.length!==1){
              const arr = item.split('$_#_$')
              if(entityNum[arr[1]]){
                entityNum[arr[1]]++
              }else {
                entityNum[arr[1]] = 1
              }
            }
          })
          this.thisIsFunc(initTxtArr, propertyIdArr, objects, objectLabelList.filter(label => label.labelType === 1))
          let init = (initTxtArr && initTxtArr.length) ? initTxtArr : getContent(initTxt)

          // 已经触发预标注
          if (preLabelStatus === 1) {
            WebSocket('pre_label_task_finish', (res, rws) => {
              if (res.data.id === markId) {
                this.queryTaskInfo();
                rws.close();
              }
            }, close => {

            }, error => {

            });
          }
          this.setState({
            entityNum,
            preLabelStatus, usedLabel,
            labelTextId: id,
            needSave: false,
            initTxt,
            dataSetId,
            isMarked,
            propertyIdArr: propertyIdArr || [],
            objectLabels: objectLabelList.filter(label => label.labelType !== 1),
            propLabels: objectLabelList.filter(label => label.labelType === 1),
            labelList:labelList || [],
            initTxtArr: init,
            relations: relationLabelList || [],
            relationArr: relationArr || [],
            entityMap: computeInitTxtArr(init),
            process: {
              labelProcess,
              segmentNum,
            },
            objects,
          }, () => {
            // 定时提交
            if (!isMarked) {
              timer = setInterval(that.autoSave.bind(that, false), window.submitTimer || 5000)
            }
          });
        }
      })
  }

  // 划词鼠标抬起事件
  funMouseUp = e => {
    const {audioMultipleRelationModalVisible,audioModalVisible,addQuestionLabelVisible,questionLabelModifyId} = this.state;
    if(audioMultipleRelationModalVisible || audioModalVisible){
      return;
    }
    if (e.target.getAttribute('role') === 'tab') {
      return;
    }
    e.preventDefault();
    if (e.target.type === 'button') {
      clearSelect();
      return;
    }
    // 禁止右键划词 防止出现划词错乱
    if (e.button === 2 && e.target.getAttribute('role') !== 'lables') {
      this.kgWarning('请使用鼠标左键进行标注');
      clearSelect();
      return;
    }

    if (e.button === 0 && e.target.getAttribute('role') === 'not-select') {
      this.setState({ id: '', delIndex: '', isDelete: false,});
    }

    let eId = e.target.id || e.target.parentElement.id;
    // eslint-disable-next-line max-len
    const { initTxtArr, markModel, labelId, labelText, labelType, propertyIdArr } = this.state;

    document.oncontextmenu = () => true;

    if (e.target.getAttribute('role') === 'relation') {
      eId = e.target.getAttribute('data-index');
      this.setState({ id: eId });
      return;
    }
    if (e.target.getAttribute('role') === 'lables') {
      if (e.button === 2) { // 鼠标右键
        document.oncontextmenu = event => { // 清除默认鼠标右键弹出菜单
          event.preventDefault();
        };
        this.setState({ id: eId, delIndex: '',isDelete: false, relationKeyword: '', unRepeatedLabelRelationObj: [], chooseMultiVisible: {}, tempRelationKeyword: '' });
      }
      if (e.button === 0) { // 鼠标左键
        this.setState({
          isDelete: true,
          delIndex: eId,
          id: ''
        });
      }
      this.setState({ editEntity: {} });
      return;
    }

    const selection = document.getSelection();
    const text = selection.toString();

    if (text.trim() === '' && eId !== 'search' && e.button !== 2) {
      clearSelect();
      this.setState({
        editEntity: {},
        searchValue: '',
        // id: '',
        isDelete: false,
        // relationKeyword: '',
      });
      return;
    }

    const startNode = selection.anchorNode.id || selection.anchorNode.parentElement.id;
    const endNode = selection.focusNode.id || selection.focusNode.parentElement.id;
    if (
      // startNode.indexOf('mark-style-markcontent') !== -1 ||
      endNode.indexOf('mark-style-markcontent') !== -1 || text.indexOf('\r') > -1 || text.indexOf('\n') > -1) {
      this.kgWarning('划词不能包含换行符');
      this.setState({ editEntity: {} });
      return;
    }

    let startIndex = Number(selection.anchorNode.id || selection.anchorNode.parentElement.id);
    let endIndex = Number(selection.focusNode.id || selection.focusNode.parentElement.id || -1);

    if (endIndex < 0 && eId !== 'search' && e.button !== 2) {
      this.kgWarning('划词包含已标注的实体');
      this.setState({ editEntity: {} });
      return;
    }

    if (startIndex > endIndex) {
      startIndex += endIndex;
      endIndex = startIndex - endIndex;
      startIndex -= endIndex;
    }
    // 包含实体的划词
    for (let i = startIndex; i <= endIndex; i++) {
      if (i >= 0 && e.button !== 2 && initTxtArr[i].length > 1 && eId !== 'search') {
        this.kgWarning((addQuestionLabelVisible || questionLabelModifyId!==0) ? '添加失败，添加问题标签仅支持划词未标注文本' :'划词包含已标注的实体');
        this.setState({ editEntity: {} });
        return;
      }
    }

    if (addQuestionLabelVisible || questionLabelModifyId!==0){
      const {initTxt} = this.state
      this.props.form.setFieldsValue({
        questionLabel: initTxtArr.slice(startIndex,endIndex+1).join(''),
      });
      this.setState({questionLabelName:initTxtArr.slice(startIndex,endIndex+1).join('')})
      return;
    }
    if (markModel === 0) {
      const uuid = createUUID();
      const { propertyIdArr, initTxtArr, markType, propLabels } = this.state;
      if (labelType && labelType === 'property') {
        propertyIdArr.push(uuid);
      }
      let arr=getMarkContent(initTxtArr, {
        startIndex,
        endIndex,
        text,
      }, {
        labelText,
        id: labelId - 1,
      }, markModel, uuid)
      this.setState({
        needSave: true,
        initTxtArr: arr,
        entityMap: computeInitTxtArr(arr),
        editEntity: {},
        propertyIdArr,
      }, () => {
        const { initTxtArr, propertyIdArr, objects, propLabels } = this.state
        this.thisIsFunc(initTxtArr, propertyIdArr, objects, propLabels)
        clearSelect();
      });
    } else {
      eId !== 'search' && this.setState({
        initTxtArr,
        editEntity: {
          startIndex,
          endIndex,
          text,
        },
        labelId: '',
        labelText: '',
        labelType: '',
      });
    }
  }

  // 划词悬浮框
  funPopover = () => {
    const { objectLabels, searchValue, labelList, markType } = this.state;
    // 解决 划词未标注，再次划词页面展示多选中前面文本
    document.getSelection().removeAllRanges();
    return (
      <div className={styles.funPopover}>
        <Input placeholder="搜索标签" id="search"
               autoComplete="off"
               onPressEnter={e => this.setState({ searchValue: e.target.value })}
               style={{ margin: '6px 0 12px' }} />
        <div>
          {
            markType - 0=== 7 ? labelList && labelList.map((item, index) => (
              <Tooltip  placement="top" title={item.labelName}><Button key={index} id={index} index={index} text={item.labelName} size="small"
                      style={{display:"block",maxWidth:'98%'}}
                      type="primary" className={styles[`kg_keyword${index % 28}`]}
                      onMouseUpCapture={this.onChooseLable}
                      data-type="object"
                      data-visible={(searchValue !== '' && item.labelName.indexOf(searchValue)
                        === -1) ? 'none' : null}><span style={{width:'100%',overflow: 'hidden', whiteSpace: 'nowrap',textOverflow: 'ellipsis'}}>
                {item.labelName}</span>
              </Button></Tooltip>
            )) :
              objectLabels && objectLabels.map((item, index) => (
                <Button key={index} id={index} index={index} text={item.labelName} size="small"
                        type="primary" className={styles[`kg_keyword${index % 28}`]}
                        onMouseUpCapture={this.onChooseLable}
                        data-type="object"
                        data-visible={(searchValue !== '' && item.labelName.indexOf(searchValue)
                          === -1) ? 'none' : null}>{item.labelName}</Button>
              ))
          }
        </div>
      </div>
    );
  };

  // 划词悬浮框
  funPopoverForProp = () => {
    const { initTxtArr, editEntity, objectLabels, propLabels, searchValue, searchValue2, markType } = this.state;
    const indexOffset = objectLabels.length;
    // 解决 划词未标注，再次划词页面展示多选中前面文本
    document.getSelection().removeAllRanges();
    return (
      <div className={styles.funPopover}>
        <Tabs size="small">
          <TabPane key="object" tab={Number(markType) === 4 ? "实体" : '事件类型'}>
            <Input placeholder="搜索标签" id="search"
                   autoComplete="off"
                   onPressEnter={e => this.setState({ searchValue: e.target.value })}
                   style={{ margin: '6px 0 12px' }} />
            <div>
              {
                objectLabels && objectLabels.map((item, index) => (
                  <Button key={index} id={index} index={index} text={item.labelName} size="small"
                          type="primary" className={styles[`kg_keyword${index % 28}`]}
                          onMouseUpCapture={this.onChooseLable}
                          data-type="object"
                          data-visible={(searchValue !== '' && item.labelName.indexOf(searchValue)
                            === -1) ? 'none' : null}>{item.labelName}</Button>
                ))
              }
            </div>
          </TabPane>
          <TabPane key="props" tab={Number(markType) === 4 ? "属性" : '实体类型'} >
            <Input placeholder="搜索标签" id="search"
                   autoComplete="off"
                   onPressEnter={e => this.setState({ searchValue2: e.target.value })}
                   style={{ margin: '6px 0 12px' }} />
            <div>
              {
                propLabels && propLabels.map((item, index) => (
                  <Button key={index} id={index} index={index} text={item.labelName} size="small"
                          type="primary" className={styles[`kg_keyword${(index + indexOffset) % 28}`]}
                          onMouseUpCapture={this.onChooseLable}
                          data-type="property"
                          data-visible={(searchValue2 !== '' && item.labelName.indexOf(searchValue2)
                            === -1) ? 'none' : null}>{item.labelName}</Button>
                ))
              }
            </div>
          </TabPane>
        </Tabs>
      </div>
    );
  };

  handleClickChange = visible => {
    const { chooseMultiVisible } = this.state;
    Object.keys(chooseMultiVisible).forEach(function (key) {
      if (key !== visible)
        chooseMultiVisible[key] = false
    })
    chooseMultiVisible[visible] = chooseMultiVisible[visible] ? !chooseMultiVisible[visible] : true;
    this.setState({
      chooseMultiVisible,
      // hovered: false,
    });
  };
  // 添加关系悬浮框
  funPopoverForRelation(e, id, arr) {
    const _this = this;
    const { relations, propertyIdArr, markType, initTxtArr, relationKeyword, unRepeatedLabelRelationObj,entityNum, relationFromToName, entityObj, chooseMultiVisible, tempRelationKeyword } = _this.state;
    const propType = markType - 0 === 4;
    const isEventType = markType - 0 === 5;
    const unRepeatedLabelRelationArr = []
    return (
      <div className={styles.addRelationBox}>
        <div style={{ width: 180 }}>
          {relations.map((val, i) => {
            // 标签与标签若多个角色，进行处理，
            unRepeatedLabelRelationObj[val.labelFromName + '__@__' + val.labelToName] = unRepeatedLabelRelationObj[val.labelFromName + '__@__' + val.labelToName] ? unRepeatedLabelRelationObj[val.labelFromName + '__@__' + val.labelToName] : []
            unRepeatedLabelRelationObj[val.labelFromName + '__@__' + val.labelToName].indexOf(val.labelRelationName) === -1
            && unRepeatedLabelRelationObj[val.labelFromName + '__@__' + val.labelToName].push(val.labelRelationName)
            if (val.labelFromName === arr[1] && unRepeatedLabelRelationArr.indexOf(val.labelFromName + val.labelToName) === -1) {
              if (isEventType) {
                //事件标注做特殊处理
                unRepeatedLabelRelationArr.push(val.labelFromName + val.labelToName)
              }
              return <a key={i} data-active={`${val.labelToName}__$__${val.labelRelationName}`
              == relationKeyword} data-index={id} data-text={val.labelRelationName}
                        title={propType ? val.labelToName : isEventType ? `${val.labelToName}` : `${val.labelRelationName}[${val.labelFromName}->${val.labelToName}]`}
                        className={styles.addRelation}
                        onClick={() => {
                          _this.setState({ relationKeyword: `${val.labelToName}__$__${val.labelRelationName}`, relationFromToName: `${val.labelFromName + '__@__' + val.labelToName}`, chooseMultiVisible: {} })
                        }} role={entityNum[val.labelToName] && entityNum[val.labelToName] > 0 ? "relation" : "noRelation"}>
                {propType ? val.labelToName : isEventType ? `${val.labelToName}` : `${val.labelRelationName}[${val.labelFromName}->${val.labelToName}]`}
              </a>
            }
          })
          }
        </div>
        <div className={styles.labelBox}>
          {initTxtArr.map((val, i) => {
            if (val.length > 1 && i != id) {
              const labelArr = val.split('$_#_$');
              // 是目标关系 或 是目标属性
              if (relationKeyword.split('__$__')[0] === labelArr[1] &&
                ((propType && propertyIdArr.indexOf(labelArr[3]) > -1) || !propType)
              ) {
                return unRepeatedLabelRelationObj[relationFromToName].length < 2 || !isEventType ? <a key={i} data-index={id} className={styles.addRelation}
                                                                                                      data-text={`${labelArr[3]}#_#${labelArr[0]}`} title={`#${i}${labelArr[0]}`}
                                                                                                      onMouseUpCapture={_this.addRelation}
                                                                                                      role="instence">
                  {`#${i} ${labelArr[0]}`}
                </a> : <Popover placement="right"
                                getPopupContainer={() => document.getElementById('markcontent')}
                                content={
                                  <div style={{ padding: 0 }} className='clearfix'>
                                    <div style={{ margin: '3px 0px' }}>
                        <span style={{ backgroundColor: colors[entityObj[arr[3]] % 28], margin: '2px 12px', padding: '1px 20px', color: '#fff', borderRadius: 4 }}>
                          {relationFromToName.split('__@__')[0]}</span>
                                      <ArrowRightOutlined style={{ color: "#29CAAF" }} />
                                      <span style={{ backgroundColor: colors[entityObj[labelArr[3]] % 28], margin: '2px 12px', padding: '1px 20px', color: '#fff', borderRadius: 4 }}>
                          {relationFromToName.split('__@__')[1]}</span>
                                    </div>
                                    <div className={styles.roleList}>
                                      {unRepeatedLabelRelationObj[relationFromToName].map(item => {
                                        return <Tooltip title={item}>
                                          <div style={{
                                            background: (tempRelationKeyword === '' && relationKeyword.split('__$__')[1] === item ||
                                              tempRelationKeyword !== '' && tempRelationKeyword.split('__$__')[1] === item) ? '#DDF7F2' : '#fff'
                                          }}
                                               onClick={() => this.setState({ tempRelationKeyword: `${relationKeyword.split('__$__')[0]}__$__${item}` })}
                                          >
                                            <Button style={{
                                              width: '100%',
                                              textAlign: 'left',
                                              border: '0px', background:
                                                (tempRelationKeyword === '' && relationKeyword.split('__$__')[1] === item || tempRelationKeyword !== '' && tempRelationKeyword.split('__$__')[1] === item) ?
                                                  '#DDF7F2' : '#fff',
                                              color:(tempRelationKeyword === '' && relationKeyword.split('__$__')[1] === item || tempRelationKeyword !== '' && tempRelationKeyword.split('__$__')[1] === item) ?
                                                '#29CCB1' : 'black'
                                            }}>
                                              <span>{item}</span>
                                            </Button>
                                          </div>
                                        </Tooltip>
                                      })}
                                    </div>
                                    <div style={{ float:'right',}}>
                                      <Button type="danger" ghost style={{ marginRight: 10 }} onClick={this.handleClickChange.bind(this, labelArr[0])}>取消</Button>
                                      <Button type="primary" key={i} data-index={id} className={styles.addRelation}
                                              data-text={`${labelArr[3]}#_#${labelArr[0]}`} title={`#${i}${labelArr[0]}`}
                                              onMouseUpCapture={_this.addRelation}>确定</Button>
                                    </div>
                                  </div>
                                }
                                title={
                                  <div style={{ padding: '9px 0px' }}><span>角色选择</span><CloseOutlined
                                    style={{ float: "right", cursor: "pointer" }}
                                    onClick={this.handleClickChange.bind(this, labelArr[0])} /></div>
                                }
                                trigger="click"
                                visible={chooseMultiVisible[labelArr[0]]}
                >
                  <Button onClick={this.handleClickChange.bind(this, labelArr[0])} className={styles.multiEntity}>
                    <span>{`#${i} ${labelArr[0]}`}</span>
                  </Button>
                </Popover>;
              }
            }
          })}
        </div>
      </div>
    );
  }

  // 查看帮助
  helpView() {
    const {markType} = this.state
    return<div className={styles.helpContainer}>
      <Tabs>
        <TabPane tab="划词标注" key="1">
          <h2>一、划词</h2>
          <h4>1.1单个划词</h4>
          <p>鼠标滑动选择某段文本，出现标签下拉选择框，选择【标签】，完成划词</p>
          <img
            src=""
            alt="" />
          <h4>1.2批量划词</h4>
          <p>选中某个【标签】，在文本中鼠标滑动选择某段文本，自动给该文本打上【标签】，可避免每次划词选择标签的重复劳动，取消批量操作只要再次点击高亮【标签】让它变灰即可</p>
          <img src={labelPng} alt="" />
        </TabPane>
        {window.isShowAudio && (markType-0===1 || markType-0 === 0) &&<TabPane tab="语音标注" key="2">
          <div className={styles.voiceMark}>
            <div style={{marginTop: 20}}>
              <h4>1.标注实体</h4>
              <p>（1）标注单个实体句式：恶心是症状/症状有恶心</p>
              <div className={styles.voiceImg}><img src={singleEntity1} alt=""/><img src={singleEntity2} alt=""/></div>
              <p>（2）标注多个实体句式：恶心和呕吐和腹痛和腹泻是症状/症状有恶心和呕吐和腹痛和腹泻</p>
              <div className={styles.voiceImg}><img src={multipleEntity2} alt=""/><img src={multipleEntity1} alt=""/>
              </div>
            </div>

            <div style={{marginTop: 20}}>
              <h4>2.标注关系</h4>
              <p>（1）标注单个关系句式：起始标签编号的xx关系是目标标签编号/起始标签编号关联目标标签编号，#1的阴性症状是#25、#1关联#25，读作：井号一/井号二十五，起始与目标标签的编号不可调换位置 </p>
              <div className={styles.voiceImg}><img src={singleRelation1} alt=""/><img src={singleRelation2} alt=""/>
              </div>
              <p>（2）标注多个关系句式：#1的阴性症状是#25和#27和#29和#31、#1关联#25和#27和#29和#31</p>
              <div className={styles.voiceImg}><img src={multipleRelation1} alt=""/><img src={multipleRelation2}
                                                                                         alt=""/></div>
            </div>
            <div style={{marginTop: 20}}>
              <h4>3.注意事项</h4>
              <p>• 语音标注时必须按照句式说话（标注内容不能与句式有重复词），否则无法识别到有效声音； </p>
              <p>• 按（空格键）或点击按钮开始/结束说话，结束后直接标注</p>
              <p>• 语音标注悬浮窗支持移动位置，不支持关闭，关闭语音标注后悬浮窗消失</p>
              <p>• 当前语音标注页面不支持划词标注与删除标注</p>
              <p>• 标注文本中出现符号、数字、英文等可以到划词页面去标注</p>
              <p>• 语音标注识别到当前文档中有重复标注内容时，直接全部标注</p>
              <p>• 语音标注过程中请勿拔掉麦克风，如麦克风不小心拔出，请刷新页面后再进行语音标注。</p>
            </div>
          </div>
        </TabPane>}
      </Tabs>
    </div>


  }

  // 添加 关系
  addRelation = e => {
    e.preventDefault();
    const index = e.target.getAttribute('data-index') - 0;
    const text = e.target.getAttribute('data-text');
    const { initTxtArr, relationArr, relationKeyword, tempRelationKeyword } = this.state;
    const relationArray = relationArr || [];
    let success = true;
    const arr = initTxtArr[index].split('$_#_$');

    relationArray.forEach(val => {
      if (val === `${arr[3]}#_$_#${tempRelationKeyword === '' ? relationKeyword.split('__$__')[1] : tempRelationKeyword.split('__$__')[1]}#_$_#${text.split(
        '#_#')[0]}`) {
        notification.warning({
          message: '添加失败',
          key: '关系已存在',
          description: '关系已存在',
        });
        success = false;
      }
    });
    if (success) {
      initTxtArr.splice(index, 1, `${initTxtArr[index]}$_#_$${text}`);
      relationArray.push(
        `${arr[3]}#_$_#${tempRelationKeyword === '' ? relationKeyword.split('__$__')[1] : tempRelationKeyword.split('__$__')[1]}#_$_#${text.split('#_#')[0]}`);
    }
    // return;
    this.setState({
      handleClickChange: false,
      needSave: true,
      initTxtArr,
      entityMap: computeInitTxtArr(initTxtArr),
      // relationKeyword: '',
      // tempRelationKeyword: '',
      relationArr: relationArray,
      // id: ''
    });
  };


  // 删除标注的实体
  delInstance(i, uuid, str) {
    const { initTxtArr, relationArr, propertyIdArr, markType } = this.state;
    const arr = relationArr.filter(val => val.indexOf(uuid) !== -1)
    const name = markType - 0 === 4 ? '属性' : '关系';
    if (arr.length > 0) {
      notification.warning({
        message: '删除失败',
        key: `请先删除实体下的${name}`,
        description: `请先删除实体下的${name}`,
      });
      this.setState({ isDelete: false });
    } else {
      const indexProp = propertyIdArr.findIndex(propId => propId === uuid);
      if (indexProp > -1) {
        propertyIdArr.splice(indexProp, 1);
      }
      let arr = getDeleteContent(initTxtArr, i, str)
      this.setState({
        needSave:true,
        initTxtArr: arr,
        entityMap: computeInitTxtArr(arr),
        delIndex: '',
        propertyIdArr,
        isDelete: false,
        id: '',
      });
    }
  }

  // 删除标注的关系
  deleteRelation(id, startIndex, type, role,entityId) {
    const { initTxtArr, relationArr, } = this.state;
    let newArray = [];
    const fromItemArray = initTxtArr[startIndex].split('$_#_$');
    let currIdx = fromItemArray.findIndex((val, i) => val.indexOf(type === 'relation' ? id[2] : id) !== -1);
    fromItemArray.splice(currIdx, 1)

    initTxtArr.splice(startIndex, 1, fromItemArray.join('$_#_$'));
    if (type === 'relation') {
      newArray = relationArr.filter(item => item !== id.join('#_$_#'));
    } else {
      relationArr.map((val, i) => {
        if ((role && val.split('#_$_#')[1]=== role && val.indexOf(entityId) !== -1 && val.indexOf(id) !== -1) || (!role && val.indexOf(id) !== -1)) {
          relationArr.splice(i, 1);
        }
      })
      newArray = relationArr
    }

    this.setState({
      initTxtArr,
      entityMap: computeInitTxtArr(initTxtArr),
      relationArr: newArray,
    });
  }

  // 点击标签 模式1单个标注
  onChooseLable = e => {
    e.preventDefault();
    const { id } = e.target;
    const uuid = createUUID();
    const labelType = e.target.getAttribute('data-type');
    const labelText = e.target.getAttribute('text');
    const { propertyIdArr, initTxtArr, markType, propLabels } = this.state;
    if (labelType && labelType === 'property') {
      propertyIdArr.push(uuid);
    }

    if (id !== null && id !== undefined) {
      const { initTxtArr, editEntity } = this.state;
      const { startIndex, endIndex, text } = editEntity;
      let arr = getMarkContent(initTxtArr, editEntity, e.target, 1, uuid, markType, labelType)
      this.setState({
          needSave: true,
          initTxtArr: arr,
          entityMap: computeInitTxtArr(arr),
          searchValue: '',
          isDelete: false,
          markModel: 1,
          editEntity: {},
          propertyIdArr,
        }, _ => {
          const { initTxtArr, propertyIdArr, objects, propLabels } = this.state
          this.thisIsFunc(initTxtArr, propertyIdArr, objects, propLabels)
        }
      );
    }
  };

  // 点击标签 模式0
  onChooseLableM2 = e => {
    e.preventDefault();
    const model = e.target.getAttribute('data-model');
    const active = e.target.getAttribute('data-active');
    const labelText = e.target.getAttribute('data-text');
    const labelType = e.target.getAttribute('data-type');
    const { markModel, initTxtArr, markType, propLabels } = this.state;
    if (active === 'true') {
      notification.info({
        message: '温馨提示',
        key: '切换标注模式',
        description: <> 当前标注模式<strong style={{ color: '#29CCB1' }}> 单个划词 </strong></>,
      });
      this.setState({
        labelId: '',
        labelText: '',
        labelType: '',
        isDelete: false,
        markModel: Number(!markModel),
      });
    } else {
      if (model === '1') {
        labelType !== 5 && labelType !== 'peoperty' && notification.info({
          message: '温馨提示',
          key: '切换标注模式',
          description: <> 当前标注模式<strong style={{ color: '#29CCB1' }}> 批量划词 </strong></>,
        });
        this.setState({
          labelId: e.target.id,
          isDelete: false,
          markModel: 0,
          labelText,
          labelType,
          editEntity: {},
        });
      }
      if (model === '0') {
        this.setState({
          labelId: e.target.id,
          isDelete: false,
          labelText,
          labelType,
        });
      }
    }
    clearSelect();
  }

  onSChange = e => {
    this.setState({ searchTopValue: e.target.value.trim() })
  }

  // 警告
  kgWarning(text) {
    clearSelect();
    notification.warning({
      message: '警告',
      key: text,
      description: text,
    });
  }

  //修改文本内容
  modifyInitTxt() {
    const { initTxtArr, initTxt } = this.state;
    if (initTxtArr.toString() !== getContent(initTxt).toString()) {
      notification.error({
        message: '操作失败',
        key: '编辑失败',
        description: '您已进行标注，如需修改内容，请重置后再行操作',
      });
      return;
    }
    this.setState({ isModify: !this.state.isModify })
  }
  // 重置划词
  onReset() {
    const _this = this;
    confirm({
      title: '确定重置已标注的内容?',
      okText: '确定',
      cancelText: '取消',
      onOk() {
        const { initTxt, markId, dataSetId } = _this.state;
        resetMark({
          id: markId,
          dataSetId,
        })
          .then(res => {
            if (res.retCode === '0') {
              notification.success({
                message: '操作成功',
                key: '重置划词',
                description: '重置划词成功',
              });
              _this.setState({
                initTxtArr: getContent(initTxt),
                relationArr: [],
                propertyIdArr: [],
              });
              _this.props.callBack();
            }
          })
      },
    });
  }

  autoSave() {
    const { needSave } = this.state;
    if (needSave) {
      this.setState({ needSave: false })
      this.onSubmit(false);
    }
  }
  //编辑标注内容
  onTextChange(e) {
    this.setState({ initTxt: e.target.value })
  }
  //提交修改后的标注内容
  onSubmitModify(isMarked) {
    const { markId, initTxt } = this.state;
    modifyMarkContent({
      id: markId,
      initTxt,
      isMarked,
    }).then(res => {
      if (res.retCode === '0') {
        this.setState({ isModify: false })
        this.queryTaskInfo()
        if (isMarked) {
          notification.success({
            message: '操作成功',
            key: '提交修改内容',
            description: '修改内容成功',
          });
          this.queryTaskInfo();
          this.props.callBack();
        }
      }
    })
  }
  // 提交划词
  onSubmit(isMarked) {
    const { markId, initTxt, initTxtArr, dataSetId, relationArr, propertyIdArr, objectLabels, propLabels, relations, firstSave,labelList,addQuestionLabelVisible,questionLabelModifyId } = this.state;
    submitMark({
      id: markId,
      initTxtArr,
      initTxt,
      dataSetId,
      relationArr,
      propertyIdArr,
      isMarked,
      labelList,
      objectLabelList: [].concat(objectLabels).concat(propLabels),
      relationLabelList: relations,
      labelExistValidate: firstSave,
    })
      .then(res => {
        if (res.retCode === '0') {
          this.setState({ firstSave: false });
          if (isMarked) {
            notification.success({
              message: '操作成功',
              key: '提交划词',
              description: '提交划词成功',
            });
            this.queryTaskInfo();
            this.props.callBack();
          }
          if (addQuestionLabelVisible || questionLabelModifyId !== 0){
            this.setState({addQuestionLabelVisible:false,questionLabelModifyId:0})
            this.queryTaskInfo();
            this.props.callBack();
          }
        }
      })
  }

  // 展开抽屉 查看 实体 关系
  openDrawer(i) {
    this.setState({
      isOpenDrawer: true, id: '', delIndex: '',isDelete: false, relationKeyword: '', unRepeatedLabelRelationObj: [],
      chooseMultiVisible: {}, tempRelationKeyword: '', editEntity: {}
    });
  }

  // 关闭抽屉
  onCloseDrawer() {
    this.setState({ isOpenDrawer: false })
  }
  // 预标注
  onClickLabelPre() {
    const { dataSetId, labelTextId, markId } = this.state;
    const labelTxt = [];
    labelTxt.push({
      labelTextId
    })

    labelPre({ dataSetId, labelTxt }).then(res => {
      if (res.retCode === '0') {
        notification.success({
          message: '操作成功',
          key: '提交预标注',
          description: '提交预标注成功',
        });
      }
      this.setState({ preLabelStatus: 1 })
    })

    WebSocket('pre_label_task_finish', (res, rws) => {
      if (res.data.id === markId) {
        this.queryTaskInfo();
        rws.close();
      }
    }, close => {

    }, error => {

    });
  }

  webSocketFunction() {
    const { dataSetId, labelTextId, markId } = this.state;
    WebSocket('pre_label_task_finish', (res, rws) => {
      if (res.data.id === markId) {
        this.queryTaskInfo();
        rws.close();
      }
    }, close => {

    }, error => {

    });
  }


  // 实体属性关系/事件抽取
  getRelationList = () => {
    const { objectLabels, initTxtArr, relationArr, propertyIdArr,  markType, showMore, entityMap, drawerSearchPropRe } = this.state;
    let isEvent = markType - 0 === 5
    const hasPropSearch = drawerSearchPropRe !== '';


    return objectLabels.map((val, index) => {
      let data = Object.keys(entityMap).reduce((pre, curr) => {
        if (entityMap[curr].labelName === val.labelName) {
          pre[curr] = entityMap[curr]
        }
        return pre
      }, {})

      return (
        <div gutter={8} key={index} className={styles.items}>
          <h2><Badge color={colors[index % 28]} text={val.labelName} /></h2>
          {
            Object.keys(data).map(key => {
              let { name, labelName, index, relationList } = data[key]
              const relation = relationArr.filter(val => val.split('#_$_#')[0] === key);
              //是否实体标签未匹配到搜索项
              const objectSearched = hasPropSearch && name.indexOf(drawerSearchPropRe) !== -1;

              let backs = []
              relation.map(item => {
                backs.push(`${item.split('#_$_#')[1]}#${item.split('#_$_#')[2]}`);
                return backs;
              })
              return (
                <div style={{ margin: '10px 0', width: '98' }} key={name}>
                  <Tooltip title={`#${index}${name}`} placement="bottomLeft">
                    <div>
                      <span className={styles.elli}> {`#${index} ${name}`} &nbsp;&nbsp;</span>
                      {relationList.length === 0 && isEvent && <Popconfirm title={'确定删除该事件类型 ？'}
                                                                           arrowPointAtCenter
                                                                           getPopupContainer={() => document.getElementById('closeDrawer')}
                                                                           onConfirm={this.delInstance.bind(this, index, key, name)}>
                        <DeleteOutlined style={{ color: 'rgba(135, 149, 161, 1)' }} />
                      </Popconfirm>}
                    </div>
                  </Tooltip>
                  {
                    relationList.length > 0 && (!drawerSearchPropRe || (drawerSearchPropRe && objectSearched)) ? <div className={styles.relation_card}>
                      {
                        backs.map((item, idx) => {
                          let reItem = item.split('#')
                          let relationItem = <div className={styles.item} key={idx}>
                            {isEvent &&
                            <Tooltip title={reItem[0]}>
                              <div className={styles.ellipsi}>
                                {reItem[0]}
                              </div>
                            </Tooltip>
                            }
                            <Tooltip title={`${entityMap[reItem[1]]?.labelName}`}>
                              <span className={styles.ellipsi} style={{ maxWidth: isEvent ? 85 : 130, }}>{`${entityMap[reItem[1]]?.labelName}`}</span>
                            </Tooltip>
                            <span><ArrowRightOutlined /></span>
                            <Tooltip title={`#${entityMap[reItem[1]]?.index}${entityMap[reItem[1]]?.name}`}>
                              <span className={styles.ellipsi} style={{ maxWidth: isEvent ? 100 : 130, textAlign: 'center' }}>
                                {`#${entityMap[reItem[1]]?.index} ${entityMap[reItem[1]]?.name}`}</span>
                            </Tooltip>
                            <Popconfirm title={markType - 0 === 5 ? '确定删除该角色？' : '确定删除本属性关系？'}
                                        getPopupContainer={() => document.getElementById('closeDrawer')}
                                        placement="topRight"
                                        onConfirm={this.deleteRelation.bind(this, reItem[1], index, '', isEvent?reItem[0]:'',key)}>
                              <a><DeleteOutlined style={{ float: 'right', lineHeight: '29px' }} /></a>
                            </Popconfirm>
                          </div>
                          return relationItem
                        })
                      }
                    </div> : <span key={`empty${index}`} className={styles.noData}>暂无</span>
                  }
                </div>
              );
            })
          }
        </div>
      );
    });
  }

  audioModalOnOk(){
    if (this.state.isModify)return
    notification.success({
      message: this.state.audioModalVisible?'语音标注已关闭': '语音标注已开启',
      // key: '提交预标注',
      duration:0.8
      // description: '提交预标注成功',
    });
    if(this.state.audioModalVisible){
      this.child.onCancelAudio()
    }
    this.setState({
      delIndex: '',
      isDelete: false,
      id: '',
      effectAudio:true,
      audioModalVisible:!this.state.audioModalVisible
    })
  }

  cancelCallback(){
    this.audioModalOnOk()
  }
  audioMultipleModal(){
    this.setState({
      audioMultipleRelationModalVisible:!this.state.audioMultipleRelationModalVisible
    })
  }
  multipleRelationCancelCallback(){
    const { targetLabelIsNotExistNum,relationLabelIsNotExistNum } = this.state
    this.audioMultipleModal()
    if (targetLabelIsNotExistNum>0){
      notification['warning']({
        message: '警告',
        key: '部分目标标签编号不存在，请检查后再试',
        description: `部分目标标签编号不存在，请检查后再试`,
      })
      this.setState({targetLabelIsNotExistNum:0,relationLabelIsNotExistNum:0})
      // return
    }
    if (relationLabelIsNotExistNum>0){
      notification['warning']({
        message: '警告',
        key: '已标注已存在关系，剩余关系请检查后再试',
        description: `已标注已存在关系，剩余关系请检查后再试`,
      })
    }
    this.setState({targetLabelIsNotExistNum:0,relationLabelIsNotExistNum:0, audioModalVisible:true,})
  }

  //校验语音标注的内容，包括实体，标签，单个标注验证
  verifyAudioContent(array,entity){
    const { initTxt, objects } = this.state
    if (initTxt.indexOf(array[1]) ===-1 && objects.indexOf(array[0]) ===-1){
      this.setState({effectAudio:false})
      return false
    }
    // 校验标注内容
    if (initTxt.indexOf(entity) ===-1){
      notification['error']({
        message: '标注失败',
        key: '暂未查询到标注内容，请检查后再试',
        description: `暂未查询到标注内容，请检查后再试`,
      })
      return false
    }
    // 校验标签
    if (objects.indexOf(array[0]) ===-1){
      notification['error']({
        message: '标注失败',
        key: '暂未查询到配置标签，请检查后再试',
        description: `暂未查询到配置标签，请检查后再试`,
      })
      return false
    }
    return true
  }

  //校验语音标注的内容，包括实体，标签，单个标注验证
  verifyAudioLabel(labelString){
    const { initTxt, objects } = this.state
    // 校验标签
    if (objects.indexOf(labelString) ===-1){
      return false
    }
    return true
  }
  // 获取实体的startIndex、endIndex
  getEntityIndex(markContent){
    const {initTxt,initTxtArr} = this.state
    let indexNum = 0 //计算在此标注内容前偏移量
    let beIncluded = false
    for (var i=0;i +indexNum !== initTxt.indexOf(markContent);i++){
      if (i+indexNum +(initTxtArr[i].split("$_#_$")[0].length-1)>initTxt.indexOf(markContent) ){
        beIncluded = true
        break
      }
      if(initTxtArr[i].indexOf("$_#_$") !==-1){
        indexNum = indexNum+ (initTxtArr[i].split("$_#_$")[0].length-1)
      }
    }
    return{
      startIndex:beIncluded ? 'included' :initTxt.indexOf(markContent)-indexNum,
      endIndex: beIncluded ? 'included' :initTxt.indexOf(markContent)-indexNum + markContent.length-1
    }
  }

  // 标注内容重复出现，获取实体的所有startIndex、endIndex
  getEntityAllIndex(markContent){
    const {initTxt,initTxtArr} = this.state

    const positions = []
    let position = initTxt.indexOf(markContent)
    while(position>-1){
      let indexNum = 0 //计算在此标注内容前偏移量
      let beIncluded = false
      for (var i=0;i +indexNum < position;i++){
        if (i+indexNum +(initTxtArr[i].split("$_#_$")[0].length-1)>initTxt.indexOf(markContent,position) ){
          beIncluded = true
          break
        }
        if(initTxtArr[i].indexOf("$_#_$") !==-1){
          indexNum = indexNum+ (initTxtArr[i].split("$_#_$")[0].length-1)
        }
      }
      positions.push({
        startIndex: beIncluded ? 'included' :position-indexNum,
        endIndex: beIncluded ? 'included' :position-indexNum + markContent.length-1
      });
      position = initTxt.indexOf(markContent,position+1);
    }
    return positions
  }

  audioRelationMark(index,text, relationKeyword,markType = 'single') {
    //关系标注
    const { initTxtArr,relationArr, tempRelationKeyword } = this.state;
    let success = true;
    const arr = initTxtArr[index].split('$_#_$');
    // 单个标注进行判断
    relationArr.forEach(val => {
      if (val === `${arr[3]}#_$_#${relationKeyword}#_$_#${text.split(
        '#_#')[0]}`) {

        // markType ==='single' && notification.warning({
        //   message: '添加失败',
        //   key: '关系已存在',
        //   description: '关系已存在',
        // });
        success = false;
      }
    });
    if (success) {
      initTxtArr.splice(index, 1, `${initTxtArr[index]}$_#_$${text}`);
      relationArr.push(
        `${arr[3]}#_$_#${relationKeyword}#_$_#${text.split('#_#')[0]}`);
    }
    this.setState({
      handleClickChange: false,
      needSave: true,
      initTxtArr,
      entityMap: computeInitTxtArr(initTxtArr),
      relationKeyword: '',
      tempRelationKeyword: '',
      relationArr: relationArr,
      id: ''
    });
  }
  getRelationKeyword(startEntity, endEntity){
    // 根据实体index，查询两个实体之间的所有关系
    const {initTxtArr,relations} = this.state
    const newRelations = relations.filter(item=>{
      return initTxtArr[startEntity] && initTxtArr[endEntity] &&
        item.labelFromName===initTxtArr[startEntity].split("$_#_$")[1] && item.labelToName === initTxtArr[endEntity].split("$_#_$")[1]
    })
    return newRelations
  }

  verifyRelationKeyword(relation){
    // 根据关系名称，验证该关系是否存在
    const {relations} = this.state
    const newRelations = relations.filter(item=>{
      return item.labelRelationName ===relation
    })
    return newRelations.length > 0
  }
  //语音识别返回的数据
  audioMarkCallback(audioContent){
    // dingwei
    // audioContent = "井号28关联井号93和井号10"
    audioContent = audioContent.replaceAll('。',"").replaceAll("，","")
    const {initTxtArr} = this.state;
    if ((audioContent.indexOf("关联") !==-1 || (audioContent.indexOf("的") !==-1 && audioContent.indexOf("是") !==-1)) && audioContent.indexOf('井号')!==-1){
      // 标注关系
      const audioContentRelation  = audioContent.replace(/井号/g,"#").replaceAll("，","");
      const startLabel = audioContentRelation.indexOf("关联") ===-1 ? audioContentRelation.split("的")[0] : audioContentRelation.split("关联")[0];// 关系起始标签
      const targetLabelArray = audioContentRelation.indexOf("关联") ===-1 ? audioContentRelation.split("是")[1].split("和")
        : audioContentRelation.split("关联")[1].split("和");// 关系标注时目标实体，可能有多个
      if (isNaN(startLabel.replace("#",""))){
        // 开始标签不是数字，没有检测到有效声音
        this.setState({effectAudio:false})
        return;
      }
      let startLabelIsExist = true // 起始标签是否存在
      let relationLabelIsExist = true // 关系是否存在
      let targetLabelIsNotExistNum = 0 // 目标标签不存在的个数
      let relationLabelIsNotExistNum = 0 // 起始标签和目标标签都存在，但是两个标签之间不存在关系
      let multipleRelationTargetLabel = [] // 关联句式，保存两个实体间有多种关系的目标标签
      let multipleRelationTempObj = {} // 关联句式，两个实体间存在多个关系
      if (initTxtArr[startLabel.replace("#","")].indexOf('$_#_$') ===-1){
        // 判断起始标签是否存在， 通过判断字符串中是否有'$_#_$'来判断当前是否是已被标注
        startLabelIsExist = false
      }
      if(audioContentRelation.indexOf("关联") ===-1){
        // 井号47的哈哈是井号97句式标注
        const relationKeyword = audioContentRelation.match(/的(\S*)是/)[1]// 关系名称
        const relationsVerifyResult = this.verifyRelationKeyword(relationKeyword)
        targetLabelArray.map(item=>{
          let labelArr = !isNaN(item.replace("#","")) && initTxtArr[item.replace("#","")] && initTxtArr[item.replace("#","")].split('$_#_$')
          let targetLabelIsExist = true
          if (isNaN(item.replace("#","")) || !initTxtArr[item.replace("#","")] || initTxtArr[item.replace("#","")].indexOf('$_#_$') ===-1){
            targetLabelIsNotExistNum ++
            targetLabelIsExist = false
            // 判断目标标签是否存在， 通过判断字符串中是否有'$_#_$'来判断当前是否是已被标注
          }
          const relationKeyWordArray = startLabelIsExist && targetLabelIsExist && this.getRelationKeyword(startLabel.replace("#",''),item.replace("#",""))// relationKeyWordArray起始标签和目标标签之间的关系
          if(startLabelIsExist && targetLabelIsExist && relationKeyWordArray.filter(item=> item.labelRelationName === relationKeyword).length ===0){
            // 起始标签与目标标签存在的情况再判断关系是否存在
            relationLabelIsNotExistNum++
            relationLabelIsExist = false
          }else {
            relationLabelIsExist = true
          }
          startLabelIsExist && targetLabelIsExist && relationLabelIsExist && this.audioRelationMark(startLabel.replace("#",""),`${labelArr[3]}#_#${labelArr[0]}`,relationKeyword)
        })
        if ((!startLabelIsExist && targetLabelIsNotExistNum >0) ||
          (!startLabelIsExist && relationLabelIsNotExistNum === targetLabelArray.length) ||
          (targetLabelIsNotExistNum === targetLabelArray.length && relationLabelIsNotExistNum === targetLabelArray.length) ||
          (!startLabelIsExist && !relationsVerifyResult) ||
          (targetLabelIsNotExistNum === targetLabelArray.length && !relationsVerifyResult)
        ){
          //起始编号与目标标签 || 起始编号与关系不存在 || 目标标签不存在与关系不存在
          this.setState({effectAudio:false})
          return;
        }
        if (targetLabelIsNotExistNum === targetLabelArray.length){
          notification['error']({
            message: '标注失败',
            key: '暂未查询到目标标签，请检查后再试',
            description: `暂未查询到目标标签，请检查后再试`,
          })
          return;
        }else if (targetLabelIsNotExistNum > 0 && targetLabelIsNotExistNum < targetLabelArray.length){
          // 部分目标标签不存在
          notification['warning']({
            message: '警告',
            key: '部分目标标签编号不存在，请检查后再试',
            description: `部分目标标签编号不存在，请检查后再试`,
          })
          // return;
        }
        if(!relationsVerifyResult || relationLabelIsNotExistNum===(targetLabelArray.length-targetLabelIsNotExistNum)){
          // 关系不存在，|| 存在的目标标签，所有关系都不存在
          notification['error']({
            message: '标注失败',
            key: '暂未查询到关联关系，请检查后再试',
            description: `暂未查询到关联关系，请检查后再试`,
          })
          return;
        }
        if (relationLabelIsNotExistNum>0){
          // 关系不存在的数量 > 0
          notification['warning']({
            message: '警告',
            key: '已标注已存在关系，剩余关系请检查后再试',
            description: `已标注已存在关系，剩余关系请检查后再试`,
          })
          return;
        }
      }else {
        // "井号5关联井号191和井号216" 句式标注
        targetLabelArray.forEach(item=>{
          const relationKeyWordArray = this.getRelationKeyword(startLabel.replace("#",''),item.replace("#",""))// relationKeyWordArray起始标签和目标标签之间的关系
          if (relationKeyWordArray.length === 0){
            // 两个实体存在并且没有关系
            if (initTxtArr[item.replace("#","")] && initTxtArr[item.replace("#","")].indexOf('$_#_$') !==-1)
            relationLabelIsNotExistNum++;
          }
          if (!initTxtArr[item.replace("#","")] ||(initTxtArr[item.replace("#","")] && initTxtArr[item.replace("#","")].indexOf('$_#_$') ===-1)){
            // 目标实体不存在
            targetLabelIsNotExistNum++
          }
          if (relationKeyWordArray.length === 1){
            //  “关联“关键词标注，但是起始标签编号和目标标签编号之间只存在1种关系，直接标注
            let labelArr = initTxtArr[item.replace("#","")].split('$_#_$')
            this.audioRelationMark(startLabel.replace("#",""),`${labelArr[3]}#_#${labelArr[0]}`,relationKeyWordArray[0].labelRelationName)
          }else if (relationKeyWordArray.length !== 0 && initTxtArr[item.replace("#","")].indexOf('$_#_$') !==-1) {
            // ”关联“关键词标注，多个关系
            multipleRelationTempObj[item] = relationKeyWordArray
            multipleRelationTargetLabel.push(item)
          }
        })
        multipleRelationTargetLabel.length !==0 &&this.setState({
          audioMultipleRelationModalVisible:true,
          audioModalVisible:false,
          multipleRelationObj:multipleRelationTempObj,
          multipleRelationTargetLabel:multipleRelationTargetLabel,
          multipleRelationStartLabel:startLabel,
          targetLabelIsNotExistNum,relationLabelIsNotExistNum
        })
      }
      if ((!startLabelIsExist && targetLabelIsNotExistNum >0)
      ){
        //起始编号与目标标签
        this.setState({effectAudio:false})
        return;
      }
      if(!startLabelIsExist){
        notification['error']({
          message: '标注失败',
          key: '暂未查询到起始标签，请检查后再试',
          description: `暂未查询到起始标签，请检查后再试`,
        })
        return;
      }
      if (targetLabelIsNotExistNum === targetLabelArray.length){
        notification['error']({
          message: '标注失败',
          key: '暂未查询到目标标签，请检查后再试',
          description: `暂未查询到目标标签，请检查后再试`,
        })
        return;
      }else if (multipleRelationTargetLabel.length ===0 && targetLabelIsNotExistNum > 0 && targetLabelIsNotExistNum < targetLabelArray.length){
        // 部分目标标签不存在
        notification['warning']({
          message: '警告',
          key: '部分目标标签编号不存在，请检查后再试',
          description: `部分目标标签编号不存在，请检查后再试`,
        })
        // return;
      }
      if(relationLabelIsNotExistNum === targetLabelArray.length-targetLabelIsNotExistNum){
        // 关系不存在的数量 === 所有存在的目标标签数量
        // if(!relationLabelIsExist){
        notification['error']({
          message: '标注失败',
          key: '暂未查询到关联关系，请检查后再试',
          description: `暂未查询到关联关系，请检查后再试`,
        })
      }
      if (relationLabelIsNotExistNum>0 && targetLabelArray.length-targetLabelIsNotExistNum > relationLabelIsNotExistNum && multipleRelationTargetLabel.length===0){
        // 关系不存在的目标标签数量 > 0
        // targetLabelArray.length-targetLabelIsNotExistNum（存在的目标标签） > relationLabelIsNotExistNum（目标标签存在且与起始标签之间不存在关系）
        // multipleRelationTargetLabel>0的话则不立马弹框，等多关系标注完再弹框
        notification['warning']({
          message: '警告',
          key: '已标注已存在关系，剩余关系请检查后再试',
          description: `已标注已存在关系，剩余关系请检查后再试`,
        })
      }
    }else if (audioContent.indexOf("是") !==-1 || audioContent.indexOf("有") !==-1){
      if (audioContent.indexOf("是") !== audioContent.lastIndexOf("是") || audioContent.indexOf("有") !== audioContent.lastIndexOf("有") ){
        // 没有检测到有效声音
        this.setState({effectAudio:false})
        return;
      }
      // 标注实体
      const {initTxt} = this.state
      const entityString = audioContent.indexOf("是") !==-1 ? audioContent.split("是")[0] : audioContent.split("有")[1]  //识别出来的实体字符串，可能有多个实体
      const labelString = audioContent.indexOf("是") !==-1 ? audioContent.split("是")[1] : audioContent.split("有")[0]  // 标签
      let entityArray = [] //实体数组，用于标注多个实体
      // const audioContent2 = '恶心是症状'
      if (entityString.indexOf("和") ===-1){
        entityString!==''&&entityArray.push(entityString)
      }else {
        // entityArray = entityString.split("和").filter(item=>item) // 过滤掉为空的实体
        entityString.split("和").map(item=>{
          // 过滤掉为空或者重复的标签
          item && entityArray.indexOf(item) === -1 && entityArray.push(item)
        })
      }
      let labelVerifyResult = false
      if (entityArray.length === 1){
        // 单个实体标注，则直接验证，验证失败贼返回
        labelVerifyResult = this.verifyAudioContent(audioContent.indexOf("是") !==-1 ? audioContent.split("是").reverse() : audioContent.split("有"),entityArray[0])
        // // 校验失败，直接返回
        if (!labelVerifyResult) return
      }else {
        // 校验标签
        labelVerifyResult = this.verifyAudioLabel(labelString)
        // if (!labelVerifyResult) return
      }
      let isExistNotMarkContent = 0// 未标注的内容有几个
      let containHaveMarked = 0// 内容包含已标注的实体的个数
      let isMarked = 0 //已被标注而且与当前要标注的标签不一样
      let singleIsMarked = 0 //已被标注而且与当前要标注的标签不一样
      let repeatedNum = 0 // 重复的标注内容数量
      let singleNum = 0 // 单个的标注内容数量
      entityArray.map(item=>{
        let tempContainHaveMarked = false // 当前内容是否包含已标注
        if (initTxt.indexOf(item) !==-1){
          isExistNotMarkContent++ // 统计标注内容存在个数
          // 获取标注内容在文本中的起始位置index
          if (initTxt.indexOf(item) === initTxt.lastIndexOf(item)){// 标注内容第一次出现的位置和最后一次出现的位置一致，说明无重复出现的标注文本
            singleNum ++
            const {endIndex,startIndex} = this.getEntityIndex(item)
            // 校验标注内容是否包含已标注的实体
            if(startIndex==='included' && endIndex==='included'){
              tempContainHaveMarked = true
              containHaveMarked++
            }else {for (let i = startIndex; i <= endIndex; i++) {
              if (initTxtArr[i].length > 1 ) {
                  tempContainHaveMarked = true
                  containHaveMarked++
                  break
              }
            }}
            if (startIndex!=='included' && endIndex!=='included' && initTxtArr[startIndex].indexOf('$_#_$') !== -1 && labelString !== initTxtArr[startIndex].split('$_#_$')[1]){
              // 已被标注且与当前要标注的标签不一样
              singleIsMarked++
            }else {
              // 因为已被标注但和当前标注的标签一致,所以containHaveMarked--是因为上面已经判断过是否包含标注的内容，虽包含已标注，但是和当前标注的一样，所以不需要判断
              // 被标注的内容与当前一致且标签一致
              startIndex!=='included' && endIndex!=='included' && initTxtArr[startIndex].indexOf('$_#_$') !== -1 && initTxtArr[startIndex].split('$_#_$')[0] === item && labelString === initTxtArr[startIndex].split('$_#_$')[1] && containHaveMarked--
            }
            // 进行标注
            const editEntity = {endIndex, startIndex, text: item,}
            const theTarget={id:0, labelText:labelString}
            !tempContainHaveMarked && labelVerifyResult && this.doAudioMark(editEntity,theTarget)
          }else {
            // 标注文本重复出现
            const positions = this.getEntityAllIndex(item)
            let isMarkedLabel = 0 // 这次新增的标注数量
            positions.map((position,index)=>{
              repeatedNum++
              let tempContainHaveMarked = false // 当前内容是否包含已标注
              const startIndex = position.startIndex!=='included' ?  position.startIndex -isMarkedLabel*(item.length -1) :position.startIndex
              const endIndex = position.endIndex!=='included' ?position.endIndex - isMarkedLabel*(item.length -1) : position.endIndex
              // 进行校验是否包含已标注的实体，有问题啊，会和判断是否已标注成当前标签重合
              if(startIndex==='included' && endIndex==='included'){
                tempContainHaveMarked = true
                containHaveMarked++
              }else{for (let i = startIndex; i <= endIndex; i++) {
                if (initTxtArr[i].length > 1 ) {
                    tempContainHaveMarked = true
                    containHaveMarked++
                    break
                }
              }}
              if (startIndex!=='included' && endIndex!=='included' && initTxtArr[position.startIndex - isMarkedLabel*(item.length -1)].indexOf('$_#_$') === -1 && !tempContainHaveMarked){
                // 未被标注，进行标注
                // 进行标注
                const editEntity = {endIndex, startIndex, text: item,}
                const theTarget={id:0, labelText:labelString}
                !tempContainHaveMarked && labelVerifyResult && this.doAudioMark(editEntity,theTarget)
                !tempContainHaveMarked && isMarkedLabel ++
              }else {
                // 已被标注
                if (startIndex!=='included' && endIndex!=='included' &&labelString !== initTxtArr[position.startIndex - isMarkedLabel*(item.length -1)].split('$_#_$')[1]){
                  // 已被标注且与当前要标注的标签不一样
                  isMarked++
                }else {
                  // 已被标注但和当前标注的标签一致，则containHaveMarked --
                  startIndex!=='included' && endIndex!=='included' && initTxtArr[position.startIndex - isMarkedLabel*(item.length -1)].indexOf('$_#_$') !== -1 &&
                  initTxtArr[position.startIndex - isMarkedLabel*(item.length -1)].split('$_#_$')[0] === item && containHaveMarked--
                }
              }
            })
          }
        }
      })
      if ((isMarked+singleIsMarked === repeatedNum+singleNum && (isMarked!==0 || singleIsMarked !== 0))|| ( repeatedNum+singleNum===containHaveMarked && containHaveMarked !==0)){
        // 进行标注的内容都被标注成其他标签，或者都包含已被标注的标签
        notification['error']({
          message: '标注失败',
          key: '内容包含已标注的实体，请检查后再试',
          description: `内容包含已标注的实体，请检查后再试`,
        })
        // return;
      }
      if (!labelVerifyResult && isExistNotMarkContent === 0){
        this.setState({effectAudio:false})
        return;
      }
      if (!labelVerifyResult){
        notification['error']({
          message: '标注失败',
          key: '暂未查询到配置标签，请检查后再试',
          description: `暂未查询到配置标签，请检查后再试`,
        })
        return;
      }
      if ((isMarked !==0 && labelVerifyResult && isMarked< repeatedNum)
        ||(containHaveMarked > 0 && labelVerifyResult && repeatedNum+singleNum!==containHaveMarked)
        || (singleIsMarked > 0 && singleIsMarked < singleNum && labelVerifyResult)){
        // 部分内容已被标注成其他标签
        notification['warning']({
          message: '警告',
          key: '部分内容已被标注为其他实体标签，剩余内容标注完成',
          description: `部分内容已被标注为其他实体标签，剩余内容标注完成`,
        })
        // return;
      }
      if (isExistNotMarkContent === 0){
        notification['error']({
          message: '标注失败',
          key: '暂未查询到标注内容，请检查后再试',
          description: `暂未查询到标注内容，请检查后再试`,
        })
        return;
      }else if (isExistNotMarkContent > 0 && isExistNotMarkContent < entityArray.length && singleNum+repeatedNum!==singleIsMarked+isMarked){
        // isExistNotMarkContent < singleNum+repeatedNum
        notification['warning']({
          message: '警告',
          key: '已标注已存在文本内容，剩余内容请检查后再试',
          description: `已标注已存在文本内容，剩余内容请检查后再试`,
        })
        return;
      }
      if (isExistNotMarkContent > 0&& isExistNotMarkContent < entityArray.length && singleNum+repeatedNum===singleIsMarked+isMarked){
        // 所有存在的被标注成其他标签并且 剩下的内容不存在
        notification['warning']({
          message: '警告',
          key: '部分标注内容不存在，请检查后再试',
          description: `部分标注内容不存在，请检查后再试`,
        })
      }

    }else{
      // 没有检测到有效声音
      this.setState({effectAudio:false})
    }
  }
  effectAudioCallback(){
    this.setState({effectAudio:true})
  }
  doAudioMark(editEntity, theTarget){
    const uuid = createUUID();
    const { initTxtArr } = this.state;
    let arr = getAudioMarkContent(initTxtArr, editEntity, theTarget, 1, uuid)
    this.setState({
      needSave: true,
      initTxtArr: arr,
      entityMap: computeInitTxtArr(arr),
      searchValue: '',
      isDelete: false,
      // markModel: 1,
      editEntity: {},
    }, _ => {
      const { initTxtArr, propertyIdArr, objects, propLabels } = this.state
      this.thisIsFunc(initTxtArr, propertyIdArr, objects, propLabels)
    })
  }
  floatOnRef = (ref) => {
    this.child = ref
  }
  handleSubmit = e => {
    e.preventDefault();
    const {markId,labelList} = this.state
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.setState({labelList:[...labelList,{
            labelId:null,
            labelType:null,
            labelName:values.questionLabel
          }]},()=>{
          this.onSubmit(false);
        })
      }
    });
  };
  handleSubmitModify = e => {
    e.preventDefault();
    const {questionLabelModifyId,labelList} = this.state
    this.props.form.validateFields((err, values) => {
      if (!err) {
        let labelLists = labelList.map(item=>{
          return item.labelId === questionLabelModifyId ? {
            labelId:item.labelId,
            labelType:item.labelType,
            labelName:values.questionLabel
          } : item
        })
        this.setState({labelList:[...labelLists]},()=>{
          this.onSubmit(false);
        })
      }
    });
  };
  addMarkQuestionLabel(){
    this.setState({addQuestionLabelVisible:true})
  }
  cancelAddQuestionLabel(){
    this.setState({addQuestionLabelVisible:false})
  }
  questionLabelEnter(itemLabel){
    // 鼠标放到问题标签上
    this.setState({questionLabelOnMouseOverId:itemLabel.labelId,isDeleteLabel:false})
  }
  questionLabelLeave(){
    // 鼠标离开问题标签上
    const {isDeleteLabel} = this.state;
    if (isDeleteLabel)return;
    this.setState({questionLabelOnMouseOverId:''})
  }
  questionLabelEnterDrawer(itemLabel){
    // 鼠标放到问题标签上
    this.setState({questionLabelOnMouseEnterIdDrawer:itemLabel.labelId,isDeleteLabel:false})
  }
  questionLabelLeaveDrawer(){
    // 鼠标离开问题标签上
    const {isDeleteLabel} = this.state;
    if (isDeleteLabel)return;
    this.setState({questionLabelOnMouseEnterIdDrawer:''})
  }
  questionLabelDelete(itemLabel){
    // 删除标签
    const {labelList} = this.state
    let labelLists = labelList.filter(item=>item.labelId !== itemLabel.labelId)
        this.setState({labelList:[...labelLists]},()=>{
          this.onSubmit(false);
        })
  }
  questionLabelModify(itemLabel){
    this.setState({questionLabelModifyId:itemLabel.labelId,questionLabelName:itemLabel.labelName})
  }
  render() {
    // eslint-disable-next-line max-len
    const { initTxtArr, relationArr, relations, isMarked, editEntity, objectLabels, propLabels, id, markId, labelId, markModel, isModify, initTxt, objects,
      Heights, searchVisible, searchTopValue, drawerSearch, drawerSearchRe, drawerSearchProp, drawerSearchPropRe, markType, propertyIdArr, isOpenDrawer,
      isDelete, delIndex, process, preLabelStatus, usedLabel, entityObj, audioModalVisible, audioMultipleRelationModalVisible,addQuestionLabelVisible, labelList,
      questionLabelOnMouseOverId, questionLabelModifyId,questionLabelName,questionLabelOnMouseEnterIdDrawer } = this.state;
    const labelListObj = {}
    labelList && labelList.map((val, index) => {
      let j = 0;
            initTxtArr.map((item, i) => {
              const labelItem = item.split('$_#_$');
              if (labelItem.length > 1 && labelItem[1] === val.labelName) {
                j++
              }
            })
      labelListObj[val.labelId] = j
    })
    const { startIndex, endIndex, text } = editEntity;
    const indexOffset = objectLabels.length;
    const hasPropSearch = drawerSearchPropRe !== '';
    const isDouble = markType - 0 === 4 || markType - 0 === 5;
    const { getFieldDecorator } = this.props.form;
    return <>
      <div className={styles.markBoxs}>
        <Row className={styles.actionBoxs}>
          {markId &&
          <>
            <Col span={17} className={styles.leftAction}>
                <span style={{ display: 'inline-block', width: 240, marginRight: 100 }}>
                  <Progress percent={Number(process.labelProcess) / Number(process.segmentNum) * 100}
                            format={percent => `${Number(process.labelProcess) || 0} / ${Number(
                              process.segmentNum) || 0}`} />
                </span>
              <span>&nbsp;&nbsp;标注模式：
                  <strong>{(audioModalVisible || audioMultipleRelationModalVisible) ? '语音标注' : ['批量划词', '单个划词'][markModel - 0]}&nbsp;&nbsp;&nbsp;</strong>
                {markType - 0 === 5 ? '已标事件类型' : markType - 0 === 7 ? '已标问答':'已标实体'}
                <strong>{getNum(initTxtArr, 'instance',  markType - 0 === 7 ? labelList : objectLabels)}</strong> 个
                {isDouble ? (markType - 0 === 5 ? <> 已标实体类型  <strong>{getNum(initTxtArr, 'property', propLabels)}</strong> 个</> :
                  <>, 已标属性  <strong>{getNum(initTxtArr, 'property', propLabels)}</strong> 个</>) :
                  ''}
                {(markType - 0 === 1 || markType - 0 === 4) &&
                <>
                  <span>, {markType - 0 === 4 ? '实体属性' : '关系'}</span>
                  <strong>{getNum(initTxtArr, 'relation', [])}</strong> 个
                </>}
                </span>
            </Col>
            <Col span={7} className={styles.rightAction}>
              <Popover placement="bottomRight" content={this.helpView(this)}>
                <QuestionCircleOutlined
                  style={{
                    color: '#8795A1',
                    margin: '0 2px',
                  }} />&nbsp;查看帮助
              </Popover>
              {(initTxtArr.toString() !== getContent(initTxt).toString() || isMarked) ?
                <Button onClick={this.onReset.bind(this)}>重置</Button> : <Button onClick={this.modifyInitTxt.bind(this)}>{isModify ? '取消' : '编辑'}</Button>
              }
              {markType - 0 !== 7 && ((preLabelStatus === 0 && usedLabel === false) || (preLabelStatus === null && usedLabel === null) ?
                <Button type="primary" onClick={this.onClickLabelPre.bind(this)} style={{ marginLeft: 10 }}>预标注</Button> :
                <Button type="primary" style={{ marginLeft: 10, opacity: '0.4' }}>预标注</Button>)
              }
              {isModify ?
                <Button type="primary" onClick={this.onSubmitModify.bind(this, false)}>提交</Button> :
                <Button type="primary" onClick={this.onSubmit.bind(this, true)}>{isMarked ? '再次提交' : '提交'}</Button>}
              <div className={styles.searchLabel}>
                <div className={styles.rig}>
                  {
                    markType -0 === 7 && <Tooltip title="添加标签" placement="bottom" ><IconFont onClick={this.addMarkQuestionLabel.bind(this)} type="icon-tianjiabiaoqian-03" /></Tooltip>
                  }
                  {(markType-0===1 || markType-0 === 0) && window.isShowAudio && <Tooltip title="语音标注" placement="bottom">
                    {
                      (audioModalVisible || audioMultipleRelationModalVisible) ? <AudioOutlined onClick={this.audioModalOnOk.bind(this)} /> : <IconFont onClick={this.audioModalOnOk.bind(this)} type="icon-audiostatic"/>
                    }
                  </Tooltip>}
                  {!searchVisible && <Tooltip title="搜索" placement="bottom"><SearchOutlined
                    onClick={() => {
                      this.setState({ searchVisible: true, searchTopValue: '' }, () => {
                        const { input } = this.inputRef; input.focus();
                      })
                    }} /></Tooltip>}
                  <Tooltip title={'查看标注结果'} placement="bottom"><TagsOutlined onClick={this.openDrawer.bind(this)} /></Tooltip>
                </div>
                {searchVisible && <div className={styles.searcherInput}>
                  <Input ref={input => {
                    this.inputRef = input;
                  }} placeholder="标签内容" value={searchTopValue} onBlur={() => {
                    this.setState({ searchVisible: false })
                  }} onChange={this.onSChange.bind(this)} />
                </div>}
              </div>
            </Col>
          </>}
        </Row>
        {
          // 阅读理解标签
          markType - 0 === 7 && markId && <div className={styles.lableBoxs} id="lableBoxs" style={{height:88}}>
            <div className={styles.buttonBox}>
              { labelList && labelList.map((item, index)=>{return questionLabelModifyId === item.labelId ? <Form layout="inline" onSubmit={this.handleSubmitModify}> <Form.Item>
                {getFieldDecorator('questionLabel', {
                  rules: [{required: true, message: 'Please input your username!'}],
                  initialValue:questionLabelName
                })(
                  <Input style={{width: 320}} placeholder="请输入或划词问题标签"/>,
                )}
              </Form.Item>
                <Form.Item>
                  <Button type="primary" icon={<CheckOutlined />} htmlType="submit" size="small"
                          style={{opacity: 1, marginRight: -15}}>
                  </Button>
                </Form.Item>
                <Form.Item>
                  <Button icon={<CloseOutlined />} htmlType="submit" size="small" style={{border: "1px solid #DDDDDD"}} onClick={_=>this.setState({questionLabelModifyId:0})}/>
                </Form.Item>
              </Form> :<span onMouseEnter={this.questionLabelEnter.bind(this,item)} onMouseLeave={this.questionLabelLeave.bind(this)} ><Button
                key={index+1} id={index+1}
                      data-text={item.labelName}
                size="small" type="primary"
                data-model={markModel} data-active={labelId == index+1}
                // className={styles[`kg_keyword${index % 28}`]}
                className={styles[`kg_keyword${index % 28}`]}
                onMouseUpCapture={this.onChooseLableM2}
                onDoubleClick={this.questionLabelModify.bind(this,item)}
                data-type="object"
                data-visible={(searchTopValue !== '' && item.labelName.indexOf(
                  searchTopValue) === -1) ? 'none' : null}
                style={(!markModel && labelId == index+1) ? { opacity: 1 } : null}
                >
                {item.labelName}
                </Button>
                {questionLabelOnMouseOverId === item.labelId && <><EditOutlined
                  onClick={this.questionLabelModify.bind(this,item)}
                  style={{padding: 5, borderRadius: 4, border: '1px solid #DDDDDD', marginRight: 5}} />
                  {labelListObj[item.labelId] === 0 && <Popconfirm
                    title="确定要删除标签吗？"
                    onConfirm={this.questionLabelDelete.bind(this, item)}
                    onCancel={_ => this.setState({isDeleteLabel: false})}
                    okText="确定"
                    cancelText="取消"
                  >
                    <DeleteOutlined
                      style={{padding: 5, borderRadius: 4, border: '1px solid #DDDDDD'}}
                      onClick={_ => this.setState({isDeleteLabel: true})} />
                  </Popconfirm>}
                  </>}
                </span>;
              })
              }

              {addQuestionLabelVisible && <Form layout="inline" onSubmit={this.handleSubmit}> <Form.Item>
                {getFieldDecorator('questionLabel', {
                  rules: [{required: true, message: 'Please input your username!'}],
                  initialValue:questionLabelName
                })(
                  <Input style={{width: 320}} placeholder="请输入或划词问题标签"/>,
                )}
              </Form.Item>
                <Form.Item>
                  <Button type="primary" icon={<CheckOutlined />} htmlType="submit" size="small"
                          style={{opacity: 1, marginRight: -15}}>
                  </Button>
                </Form.Item>
                <Form.Item>
                  <Button icon={<CloseOutlined />} htmlType="submit" size="small" style={{border: "1px solid #DDDDDD"}} onClick={this.cancelAddQuestionLabel.bind(this)}/>
                </Form.Item>
              </Form>}
              {
                markId && objectLabels && objectLabels.map((item, index) => {
                  const i = index + 1;
                  return (<Button key={i} id={i} data-text={item.labelName} size="small" type="primary"
                               data-model={markModel} data-active={labelId == i}
                               className={styles[`kg_keyword${index % 28}`]}
                               onMouseUpCapture={this.onChooseLableM2}
                               data-type="object"
                               data-visible={(searchTopValue !== '' && item.labelName.indexOf(
                                 searchTopValue) === -1) ? 'none' : null}
                               style={(!markModel && labelId == i) ? { opacity: 1 } : null}>
                        {item.labelName}
                      </Button>
                  )
                })
              }
            </div>
          </div>
        }
        {markType - 0 !== 7 && <div className={markId && (isDouble || (markType - 0 === 1 && (audioModalVisible || audioMultipleRelationModalVisible))) ? styles.labelBoxLeft : styles.lableBoxs}
              id="lableBoxs">
          {markId && (isDouble || (markType - 0 === 1 && (audioModalVisible || audioMultipleRelationModalVisible))) && (
            <div className={styles.title}>{markType - 0 === 5 ? '事件类型标签' : '实体标签'}:</div>)}
          <div className={markId && (isDouble || (markType - 0 === 1 && (audioModalVisible || audioMultipleRelationModalVisible))) ? styles.buttonBox : ''}>
            {
              markId && objectLabels && objectLabels.map((item, index) => {
                const i = index + 1;
                return (
                  audioModalVisible || audioMultipleRelationModalVisible ?
                    <Button key={i} id={i} data-text={item.labelName} size="small" type="primary"
                            data-model={markModel} data-active={labelId == i}
                            className={styles[`kg_keyword${index % 28}`]}
                            data-visible={(searchTopValue !== '' && item.labelName.indexOf(
                              searchTopValue) === -1) ? 'none' : null}
                    >
                      {item.labelName}
                    </Button>
                    : <Button key={i} id={i} data-text={item.labelName} size="small" type="primary"
                              data-model={markModel} data-active={labelId == i}
                              className={styles[`kg_keyword${index % 28}`]}
                              onMouseUpCapture={this.onChooseLableM2}
                              data-type="object"
                              data-visible={(searchTopValue !== '' && item.labelName.indexOf(
                                searchTopValue) === -1) ? 'none' : null}
                              style={(!markModel && labelId == i) ? {opacity: 1} : null}>
                      {item.labelName}
                    </Button>
                )
              })
            }
          </div>
        </div>}
        {markId && (isDouble || (markType - 0 === 1 && audioModalVisible) || (markType - 0 === 1 &&audioMultipleRelationModalVisible)) && (<div className={styles.labelBoxRight}>
            <div className={styles.title}>{markType - 0 === 5 ? '实体类型标签' : markType - 0 === 1 ? '关系标签' : '属性标签'}:</div>
            <div className={styles.buttonBox}>
              {
                markType - 0 !== 1 && markId && propLabels && propLabels.map((item, index) => {
                  const i = index + indexOffset + 1;
                  return (
                    <Button key={i} id={i} data-text={item.labelName} size="small" type="primary"
                            data-model={markModel} data-active={labelId == i}
                            className={styles[`kg_keyword${(index + indexOffset) % 28}`]}
                            onMouseUpCapture={this.onChooseLableM2}
                            data-type="property"
                            data-visible={(searchTopValue !== '' && item.labelName.indexOf(
                              searchTopValue) === -1) ? 'none' : null}
                            style={(!markModel && labelId == i) ? { opacity: 1 } : null}>
                      {item.labelName}
                    </Button>
                  )
                })
              }
              {
                markType - 0 === 1 && markId && relations && relations.map((item, index) => {
                  const i = index + indexOffset + 1;
                  return (
                    <Button key={i} id={i} data-text={item.labelRelationName} size="small" type="primary"
                            data-model={markModel} data-active={labelId == i}
                            className={styles[`kg_keyword${(index + indexOffset) % 28}`]}
                      // onMouseUpCapture={this.onChooseLableM2}
                            data-type="relation"
                            data-visible={((!audioModalVisible && !audioMultipleRelationModalVisible)&&searchTopValue !== '' && item.labelRelationName.indexOf(
                              searchTopValue) === -1) ? 'none' : null}
                            style={(!markModel && labelId == i) ? { opacity: 1 } : null}>
                      {item.labelRelationName}
                    </Button>
                  )
                })
              }
            </div></div>
        )}
        {
          isModify ?
            <>
              <div id={styles.markcontent} style={{ height: `${Heights - 168}px` }}>
                <Form>
                  {initTxt && <TextArea defaultValue={initTxt} autoSize onChange={this.onTextChange.bind(this)} />}
                </Form>
              </div>
              {/*<Button type="primary" onClick={this.onSubmit.bind(this, false)}>提交</Button>*/}
            </>
            :
            <div id='markcontent' style={{ position:'relative',height: `${Heights - 200}px`,overflowY:'scroll' }} >
              <div className={styles.markcontent} onMouseUpCapture={e => this.funMouseUp(e)}>
                {markId ? initTxtArr.map((item, index) => {
                  const boolean = index <= endIndex - 0 && index >= startIndex - 0;
                  if (index === startIndex && text.trim() && markModel === 1) {
                    return <Popover key={index} placement="bottomLeft"
                                    title={<h4 className={styles.ellipsi} style={{
                                      maxWidth: 360,
                                      fontSize: 14,
                                      backgroundColor: '#F0F2F5',
                                      padding: '4px 8px',
                                      margin: '8px 0',
                                      color: '#606F7B',
                                    }} title={editEntity.text}>{editEntity.text}</h4>}
                                    visible
                                    content={isDouble ? this.funPopoverForProp(this) : this.funPopover(this)}
                                    getPopupContainer={() => document.getElementById('markcontent')}>
                    <span key={index} id={index} role={`${boolean ? 'selected' : 'not-select'}`}>
                      {item}
                    </span>
                    </Popover>
                  } if (item.length === 1) { // &#10;换行   &#13;回车
                    if (item == '\n') return <br key={index} />;
                    if (item == ' ') {
                      return <span key={index} id={index} role={`${boolean ? 'selected'
                        : 'not-select'}`}>&nbsp;</span>;
                    }
                    return <span key={index} id={index}
                                 role={`${boolean ? 'selected' : 'not-select'}`}>{item}</span>;
                  }
                  let txt = '';
                  const arr = item.split('$_#_$');
                  arr.map((val, j) => {
                    if (j > 3) {
                      txt += `#${queryIndex(initTxtArr, val.split('#_#')[0])}\n`;
                    }
                  })
                  const span =
                    <span key={index} id={index} role="lables"
                          className={styles[`kg_keyword${markType -0 === 7 ? questionLabelGetIndexByContent(arr,labelList) : getIndexByContent(objectLabels, propLabels, propertyIdArr, arr)
                          % 28}`]} data-info={`${arr[0]}`}>
                    <sub role="lables" data-info={`${arr[0]}`}>#{index} </sub>
                      {`${arr[0]}`}
                      {markType -0 !== 7 && <sub role="lables" data-info={`${arr[0]}`}>{`${arr[1]}`}
                        {markType - '0' === 5 && objects.indexOf(arr[1]) > -1 && '触发词'}</sub>}
                      {
                        txt && <Popover placement="bottom" content={<div style={{ margin: '3px 0px' }} className={styles.container}>
                          {initTitle(arr, relationArr).map(item => {
                            let splitItem=item.split('$_#_$_$_#');
                            return (
                              <div style={{ display: 'table-row' }}>
                                <div className={styles.labelItemContents}>
                                  <div className={styles.labelItemContent} style={{ color: "#37BC9B", margin: '2px 0px' }}>{queryLabelContent(initTxtArr,
                                    splitItem[0]).length > 30 ? splitItem[0].slice(0, 30) + '...' : splitItem[0]
                                  }</div></div>
                                <div className={styles.labelItemContents}><div className={styles.labelItemContent} style={{ backgroundColor: colors[entityObj[splitItem[3]] % 28] }}>{
                                  splitItem[1].length > 30 ? splitItem[1].slice(0, 30) + '...' : splitItem[1]
                                }</div></div>
                                <ArrowRightOutlined style={{ color: "#29CAAF" }} />
                                <div className={styles.labelItemContents}><div className={styles.labelItemContent} style={{ backgroundColor: colors[entityObj[splitItem[4]] % 28], }}>{
                                  queryLabelContent(initTxtArr, splitItem[4]).length > 30 ?
                                    queryLabelContent(initTxtArr, splitItem[4]).slice(0, 30) + '...' :
                                    queryLabelContent(initTxtArr, splitItem[4])
                                }</div></div>
                              </div>
                            );
                          })}
                        </div>
                        }
                        ><strong key={txt}
                                 className={styles.reStrong}
                                 onClick={this.openDrawer.bind(this, index)}>{txt}</strong>
                        </Popover>
                      }
                  </span>;
                  if (`${index}` === id && (markType - 0 === 1 || (isDouble && propertyIdArr.indexOf(arr[3]) === -1))) {
                    return <Popover key={index} placement="bottomLeft" visible
                                    content={this.funPopoverForRelation(this, id, arr)}
                                    getPopupContainer={() => document.getElementById('markcontent')}>
                      {span}
                    </Popover>
                  }
                  return (
                    <Popconfirm key={index} title="确定删除该标注?"
                                       style={{ padding: 0, fontSize: 12 }}
                                       getPopupContainer={() => document.getElementById('markcontent')}
                                       visible={index === delIndex - 0 && isDelete}
                                       icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
                                       onConfirm={this.delInstance.bind(this, index, `${arr[3]}`,
                                         `${arr[0]}`)}
                                       onCancel={_ => {
                                         this.setState({
                                           delIndex: '',
                                           isDelete: false,
                                         })
                                       }}
                    >{span}</Popconfirm>
                  );
                }) : <Empty style={{ marginTop: 200 }} />}
              </div>
            </div>
        }
      </div>
      <div>
        <Drawer onClose={this.onCloseDrawer.bind(this)} visible={isOpenDrawer} width={660}
        >
          <Tabs defaultActiveKey="1">
            {(markType - 0 === 1 || markType - 0 === 4 || markType - 0 === 5) &&
            <TabPane tab={markType - 0 === 5 ? '已标注事件' : `${markType - 0 === 4 ? '实体属性' : '已添加关系'}`} key="1" className={styles.relationView}
                     id='closeDrawer' >
              {markType - 0 === 1 && <Search placeholder="关系名称" onSearch={value => { this.setState({ drawerSearchRe: value }) }}
                                             style={{ width: 200 }} />}
              {isDouble && <Search placeholder="关键字" onSearch={value => {
                this.setState({ drawerSearchPropRe: value })
              }}
                                   style={{ width: 200 }} />}
              {markType - 0 === 1 &&
              relations.map((val, index) => {
                let j = 0;
                return (
                  <div gutter={8} key={index} className={styles.items}
                              data-visible={(drawerSearchRe !== '' && val.labelRelationName.indexOf(
                                drawerSearchRe) === -1) ? 'none' : 'block'}>
                    <h2>{val.labelRelationName} <span style={{
                      fontSize: 14,
                      fontWeight: 700,
                    }}>&nbsp;&nbsp;{val.labelFromName} <SwapRightOutlined /> {val.labelToName}</span>
                    </h2>
                    {relationArr.length > 0 ?
                      relationArr.map((item, i) => {
                        const relationItem = item.split('#_$_#');
                        if (relationItem[1] === val.labelRelationName && getTypeById(initTxtArr,
                          relationItem[0]) === val.labelFromName && getTypeById(initTxtArr,
                          relationItem[2]) === val.labelToName) {
                          return (
                            <div key={i} className={styles.item}>
                                  <span className={styles.ellipsi}>
                                    #{queryIndex(initTxtArr, relationItem[0], true)}&nbsp;
                                  </span>
                              <span><ArrowRightOutlined /></span>
                              <span className={styles.ellipsi}>#{queryIndex(initTxtArr,
                                relationItem[2], true)}&nbsp;</span>
                              <div className='delRelationpop'>
                                <Popconfirm title="确定删除关系标注？"
                                            placement="topRight"
                                            onConfirm={this.deleteRelation.bind(this, relationItem, queryIndex(initTxtArr, relationItem[0]), 'relation')}
                                            getPopupContainer={() => document.getElementById('closeDrawer')}
                                >
                                  <a><DeleteOutlined /></a>
                                </Popconfirm>
                              </div>

                            </div>
                          );
                        }
                        j++;
                        if (j === relationArr.length) {
                          return <span key={i} className={styles.noData}>暂无</span>
                        }
                      }) :
                      <span key={`empty${index}`} className={styles.noData}>暂无</span>
                    }
                  </div>
                );
              })
              }
              {isDouble && this.getRelationList()}
            </TabPane>}
            {markType - 0 === 7 && <TabPane
              tab={"已标注问答"} key="2" className={styles.relationView}
              id='markedEntity'
            >
              <Search placeholder={"问题标签"}
                      onSearch={value => this.setState({ drawerSearch: value })}
                      style={{ width: 200 }} />
              {
                labelList && labelList.map((val, index) => {
                  let j = 0;
                  return (
                    <div gutter={8} key={index} className={styles.items}
                                data-visible={(drawerSearch !== '' && val.labelName.indexOf(
                                  drawerSearch) === -1) ? 'none' : 'block'}>
                      <span onMouseEnter={this.questionLabelEnterDrawer.bind(this,val)} onMouseLeave={this.questionLabelLeaveDrawer.bind(this)}
                          style={{background:questionLabelOnMouseEnterIdDrawer === val.labelId? '#f0f2f5' :'',padding:'0px 8px',height:27,lineHeight:'27px',margin:'10px 0px',maxHeight:'96%',overflow: "hidden",
                            whiteSpace: 'nowrap',
                            textOverflow: 'ellipsis'}}>
                        <Badge color={colors[index % 10]} text={val.labelName} />
                        {labelListObj[val.labelId] === 0 && questionLabelOnMouseEnterIdDrawer === val.labelId
                        && <Popconfirm
                          title="确定要删除标签吗？"
                          onConfirm={this.questionLabelDelete.bind(this,val)}
                          onCancel={_=>this.setState({isDeleteLabel:false})}
                          okText="确定"
                          cancelText="取消"
                        >
                          <DeleteOutlined onClick={_=>this.setState({isDeleteLabel:true})} />
                        </Popconfirm> }
                      </span>
                      <div className={styles.questionLabelItem}>
                        {
                          initTxtArr.map((item, i) => {
                            const labelItem = item.split('$_#_$');
                            if (labelItem.length > 1 && labelItem[1] === val.labelName) {
                              return (
                                <Tooltip  title={labelItem[0]} placement="top"> <span key={i} className={styles.questionLabelItemSpan}>#{`${i} ${labelItem[0]}`}&nbsp;&nbsp;
                                  <Popconfirm title={'确定删除问答？'}
                                              arrowPointAtCenter
                                              getPopupContainer={() => document.getElementById('markedEntity')}
                                              onConfirm={this.delInstance.bind(this, i, labelItem[3], labelItem[0])}>
                                    <CloseOutlined />
                                  </Popconfirm>
                                </span>
                                </Tooltip>
                              );
                            }
                            // j++;
                            // if (j === initTxtArr.length) {
                            //   return <span key={i} className={styles.noData}>暂无</span>
                            // }
                          })
                        }
                      </div>
                    </div>
                  );
                })
              }
            </TabPane>}
            {markType - 0 !== 5 && markType - 0 !== 7 && <TabPane
              tab={"已标注实体"} key="2" className={styles.relationView}
              id='markedEntity'
            >
              <Search placeholder={markType - 0 === 5 ? '类别类型' : "实体类型"}
                      onSearch={value => this.setState({ drawerSearch: value })}
                      style={{ width: 200 }} />
              {
                objectLabels.map((val, index) => {
                  let j = 0;
                  return (
                    <div gutter={8} key={index} className={styles.items}
                                data-visible={(drawerSearch !== '' && val.labelName.indexOf(
                                  drawerSearch) === -1) ? 'none' : 'block'}>
                      <h2><Badge color={colors[index % 10]} text={val.labelName} /></h2>
                      <div className={styles.labelItem}>
                        {
                          initTxtArr.map((item, i) => {
                            const labelItem = item.split('$_#_$');
                            if (labelItem.length > 1 && labelItem[1] === val.labelName) {
                              return (
                                <span key={i}
                                             className={styles.ellipsi}>#{`${i} ${labelItem[0]}`}&nbsp;&nbsp;
                                  <Popconfirm title={markType - 0 === 5 ? '确定删除触发词？' : '确定删除实体？'}
                                              arrowPointAtCenter
                                              getPopupContainer={() => document.getElementById('markedEntity')}
                                              onConfirm={this.delInstance.bind(this, i, labelItem[3], labelItem[0])}>
                                    <CloseOutlined />
                                  </Popconfirm>
                                </span>
                              );
                            }
                            j++;
                            if (j === initTxtArr.length) {
                              return <span key={i} className={styles.noData}>暂无</span>
                            }
                          })
                        }
                      </div>
                    </div>
                  );
                })
              }
            </TabPane>}
            {isDouble &&
            <TabPane tab={markType - 0 === 5 ? '已标注实体' : "已标注属性"} key="3" className={styles.relationView}
                     id='markedRelation'
            >
              <Search placeholder={markType - 0 === 5 ? '实体名' : "属性名"} onSearch={value => this.setState({ drawerSearchProp: value })}
                      style={{ width: 200 }} />
              {
                propLabels.map((val, index) => {
                  let j = 0;
                  return (
                    <div gutter={8} key={index} className={styles.items}
                                data-visible={(drawerSearchProp !== '' && val.labelName.indexOf(
                                  drawerSearchProp) === -1) ? 'none' : 'block'}>
                      <h2><Badge color={colors[(index + objectLabels.length) % 28]} text={val.labelName} /></h2>
                      <div className={styles.labelItem}>
                        {
                          initTxtArr.map((item, i) => {
                            const labelItem = item.split('$_#_$');
                            if (labelItem[1] === val.labelName) {
                              return (
                                <span key={i}
                                             className={styles.ellipsi}>#{`${i} ${labelItem[0]}`}&nbsp;&nbsp;
                                  <Popconfirm title={markType - 0 === 5 ? '确定删除实体？' : '确定删除属性？'}
                                              getPopupContainer={() => document.getElementById('markedRelation')}
                                              onConfirm={this.delInstance.bind(this, i, labelItem[3], labelItem[0])}>
                                      <CloseOutlined />
                                    </Popconfirm>
                                  </span>
                              );
                            }
                            j++;
                            if (j === initTxtArr.length) {
                              return <span key={i} className={styles.noData}>暂无</span>
                            }
                          })
                        }
                      </div>
                    </div>
                  );
                })
              }
            </TabPane>
            }
          </Tabs>
        </Drawer>
      </div>

      <FloatWindow audioModalVisible={audioModalVisible} cancelCallback={this.cancelCallback.bind(this)}
                   audioMarkCallback={this.audioMarkCallback.bind(this)} effectAudio={this.state.effectAudio}
                   effectAudioCallback={this.effectAudioCallback.bind(this)}
                   onRef={this.floatOnRef}
      />
      <AudioMultipleRelationModal audioMultipleRelationModalVisible={audioMultipleRelationModalVisible}
                                  multipleRelationObj={this.state.multipleRelationObj}
                                  multipleRelationTargetLabel={this.state.multipleRelationTargetLabel}
                                  multipleRelationStartLabel={this.state.multipleRelationStartLabel}
                                  initTxtArr={this.state.initTxtArr}
                                  markCallback={this.audioRelationMark.bind(this)}
                                  relationArr={this.state.relationArr}
                                  multipleRelationCancelCallback={this.multipleRelationCancelCallback.bind(this)}>

      </AudioMultipleRelationModal>
    </>;
  }
}
const Marks = Form.create()(Mark);
export default Marks
